package com.shixun.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shixun.domain.Account;
import com.shixun.domain.Dormitory;
import com.shixun.domain.Sd;
import com.shixun.domain.Student;
import com.shixun.dto.StudentDormitoryDto;
import com.shixun.dto.StudentDto;
import com.shixun.dto.StudentOrPasswordDto;
import com.shixun.dto.StudentPageDto;
import com.shixun.exception.exception.DormException;
import com.shixun.mapper.AccountMapper;
import com.shixun.mapper.DormitoryMapper;
import com.shixun.mapper.StudentMapper;
import com.shixun.service.AccountService;
import com.shixun.service.DormitoryService;
import com.shixun.service.SdService;
import com.shixun.service.StudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shixun.utils.R;
import com.shixun.utils.RandomNumbers;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author shixun
 * @since 2023-06-10
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private SdService sdService;
    @Autowired
    private DormitoryMapper dormitoryMapper;

    @Value("${dorm.path}")
    private String basePath;
    @Value("${dorm.errPath}")
    private String errPath;

    @Override
    @Transactional  //事物回滚
    public R insertByFile(MultipartFile file) {
        String errMsg = "";
        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
        if (!substring.equals("txt")) {
            throw new DormException("文件后缀只能是txt");
        }

        //把文件存入指定路径
        String finalPath = basePath + originalFilename;
        List<String> students = new ArrayList<>();
        try {
            file.transferTo(new File(finalPath));
            File file1 = new File(finalPath);
            students = FileUtils.readLines(file1);
            students.remove(students.get(0));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (students.size() == 0) {
            throw new DormException("导入失败");
        } else {
            //验证导入数据正确性,把不合理的数据提取出来，合理的加入数据库
            List<String> list = verifyData(students);//这些是未加入数据库的名单
            errMsg = originalFilename;
            try {
                FileUtils.writeLines(new File(errPath + errMsg), list);
            } catch (IOException e) {
                throw new DormException("写入错误信息失败");
            }
            File file1 = new File(finalPath);
            file1.delete();
        }
        return new R(1, "导入学生信息成功", errMsg);
    }


    private List<String> verifyData(List<String> students) {
        List<String> list = new ArrayList<>();
        for (String student : students) {
            String[] split = student.split("，");
            List<String> s = new ArrayList<>();
            if (split.length <= 3) {
                s.add("输入信息不完整");
            } else {
                String sex = split[1];
                String phone = split[2];
                if (!sex.equals("男") && !sex.equals("女")) {
                    s.add("性别输入有误");
                }
                String regex = "[1][34578][0-9]{9}";
                if (!phone.matches(regex)) {
                    s.add("手机号码输入有误");
                } else {
                    LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(Student::getPhone, phone);
                    Student student1 = this.getOne(queryWrapper);
                    if (student1 != null) {
                        s.add("该学生已经存在");
                    }
                }
            }

            //这里s.size() > 0的意思是如果输入有误就把错误信息加入s里面，如果都没有错误，s这个集合长度就为空，就可以加入数据库
            if (s.size() > 0) {
                String join = StringUtils.join(s, "，");
                String s1 = student + " 出错原因：" + join;
                list.add(s1);
            } else {
                //加入数据库
                addStudent(split);
            }
        }
        return list;
    }

    private void addStudent(String[] split) {
        String name = split[0];
        String sex = split[1];
        String phone = split[2];
        String profession = split[3];
        Student student = new Student();
        student.setSname(name);
        student.setPhone(phone);
        student.setSex(sex);
        student.setProfession(profession);
        String substring = phone.substring(phone.length() - 4, phone.length());
        String s = RandomNumbers.generateValidateCode();

        //生存学号原则：随机六位数加手机号后四位
        String sno = s + substring;
        student.setSno(sno);
        this.save(student);
        Account account = new Account();
        account.setUpdateTime(LocalDateTime.now());
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getPhone, phone);
        Student student1 = this.getOne(queryWrapper);
        Long id = student1.getId();
        account.setSid(id);
        accountMapper.insert(account);
    }


    /**
     * 插入单条数据
     *
     * @param studentDto
     * @return
     */


    @Override
    @Transactional
    public R insertOne(StudentDto studentDto) {
        String phone = studentDto.getPhone();
        String sex = studentDto.getSex();
        String regex = "[1][34578][0-9]{9}";
        if (!phone.matches(regex)) {
            throw new DormException("手机号码输入有误");
        }

        if (!sex.equals("男") && !sex.equals("女")) {
            throw new DormException("性别输入有误");
        }
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getPhone, phone);
        Student one = this.getOne(queryWrapper);
        if (one != null) {
            throw new DormException("该学生已经存在");
        }
        Student student = new Student();
        BeanUtils.copyProperties(studentDto, student);
        String substring = phone.substring(phone.length() - 4, phone.length());
        String s = RandomNumbers.generateValidateCode();

        //生存学号原则：随机六位数加手机号后四位
        String sno = s + substring;
        student.setSno(sno);
        this.save(student);
        Account account = new Account();
        account.setUpdateTime(LocalDateTime.now());
        LambdaQueryWrapper<Student> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Student::getPhone, phone);
        Student student1 = this.getOne(queryWrapper1);
        Long id = student1.getId();
        account.setSid(id);
        accountMapper.insert(account);
        return new R(1, "新增成功", null);
    }

    @Override
    @Transactional
    public R updateStudent(StudentOrPasswordDto studentOrPasswordDto) {
        //拿出全部数据
        String password = studentOrPasswordDto.getPassword();
        String profession = studentOrPasswordDto.getProfession();
        Long id = studentOrPasswordDto.getId();

        //更新的学生信息
        Student student = this.getById(id);
        String phone = studentOrPasswordDto.getPhone();
        //验证数据合法性
        String regex = "[1][34578][0-9]{9}";
        if (!phone.matches(regex)) {
            throw new DormException("手机号码输入有误");
        }


        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Student::getPhone, phone);
        List<Student> list = this.list(queryWrapper);
        if (list.size() > 1) {
            throw new DormException("该手机号已存在");
        }


        //先更新学生表
        student.setPhone(phone);
        student.setProfession(profession);
        this.updateById(student);

        LambdaQueryWrapper<Account> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Account::getSid, id);
        Account account = accountMapper.selectOne(queryWrapper1);
        //如果密码不为空，则更新密码表
        if (password != null) {
            String s = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
            account.setPassword(s);
        }
        accountMapper.updateById(account);
        return new R(1, "更新成功", null);
    }

    @Override
    public R pageStudent(int page, int size, String name, String profession) {
        Page<Student> page1 = new Page<>(page, size);
        LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(name != null, Student::getSname, name);
        queryWrapper.like(profession != null, Student::getProfession, profession);
        Page<Student> page2 = this.page(page1, queryWrapper);
        List<Student> students = page2.getRecords();
        List<StudentDormitoryDto> studentDormitoryDtos = new ArrayList<>();
        if (students.size() > 0) {
            for (Student student : students) {
                Long id = student.getId();
                LambdaQueryWrapper<Sd> queryWrapper1 = new LambdaQueryWrapper<>();
                queryWrapper1.eq(Sd::getSid, id);
                Sd sd = sdService.getOne(queryWrapper1);

                StudentDormitoryDto studentDormitoryDto = new StudentDormitoryDto();
                BeanUtils.copyProperties(student, studentDormitoryDto);
                if (sd != null) {
                    Long did = sd.getDid();
                    Dormitory dormitory = dormitoryMapper.selectById(did);
                    String dormitory1 = dormitory.getDormitory();
                    studentDormitoryDto.setDormitory(dormitory1);
                }
                studentDormitoryDtos.add(studentDormitoryDto);
            }
        }
        StudentPageDto studentPageDto = new StudentPageDto();
        studentPageDto.setStudentDormitoryDtos(studentDormitoryDtos);
        studentPageDto.setPages(page2.getPages());
        studentPageDto.setSize(page2.getSize());
        studentPageDto.setTotal(page2.getTotal());
        studentPageDto.setCurrent(page2.getCurrent());
        return new R(1, "查询成功", studentPageDto);


    }

    @Override
    @Transactional
    public void removes(List<Long> ids) {
        //先查出学生
        for (Long id : ids) {
            Student student = this.getById(id);
            if (student != null) {
                //找到学生宿舍
                LambdaQueryWrapper<Sd> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Sd::getSid, id);
                Sd sd = sdService.getOne(queryWrapper);
                if (sd != null) {
                    Long did = sd.getDid();
                    Dormitory dormitory = dormitoryMapper.selectById(did);
                    dormitory.setNowCapacity(dormitory.getNowCapacity() - 1);
                    dormitoryMapper.updateById(dormitory);
                }
                this.removeById(id);
            }
        }
    }
}
